"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 归档日志目录
Case Name   : 归档时归档目录无写权限
Create At   : 2020/07/01
Owner       : @wan005
Description :
    1、设置归档相关参数
    2、执行大量数据插入事务
    3、执行大量数据插入事务时人为修改归档目录权限无写权限
    4、验证相关日志信息
Expect      :
    1、设置归档相关参数成功
    2、开始执行大量数据插入事务
    3、执行大量数据插入事务时人为修改归档目录权限无写权限成功
    4、验证相关日志信息存在相应信息"The failed archive command was"
History     :
    modified: 2021/2/9  modified by @peilinqian,清理创建的归档目录
    modified: 2021/3/17  modified by @peilinqian,修改脚本，增加插入数据量，判断数据插入成功；增加等待时长
    modified: 2022/2/16  modified by @wan005,优化Expect信息，优化日志跨凌晨获取
"""

import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class NoneArchivePath(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('----Opengauss_Reliability_Dbsys_Case036.py start----')
        self.pri_root = Node(node='PrimaryRoot')
        self.pri_dbuser = Node(node='PrimaryDbUser')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.constant = Constant()

        self.conf_path = os.path.join(macro.DB_INSTANCE_PATH,
                                      macro.DB_PG_CONFIG_NAME)
        self.arch_path = macro.ARCH_PATH
        self.log_path = os.path.join(macro.PG_LOG_PATH,
                                     macro.DN_NODE_NAME.split('/')[0])

        self.max_num = 10000
        self.loop_num = 10
        self.table_test = 't_Dbsys_Case036'
        self.create_sql = f'drop table if exists {self.table_test};' \
            f'create table {self.table_test}(id int);'
        self.insert_sql = f'''begin 
            for i in 1..{self.max_num} loop
            insert into {self.table_test} values(i);
            end loop;
            end;'''
        self.select_sql = f'select count(*) from {self.table_test};'
        self.drop_sql = f'drop table {self.table_test};'

    def test_main(self):
        self.log.info('----修改归档参数并新建归档路径----')
        set_result = self.pri_sh.executeGsguc('reload',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              'archive_mode = on')
        self.assertTrue(set_result)
        archive_cmd = f"archive_command ='cp --remove-destination" \
            f" %p {self.arch_path}/%f'"
        set_result = self.pri_sh.executeGsguc('reload',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              archive_cmd)
        self.assertTrue(set_result)
        set_result = self.pri_sh.executeGsguc('reload',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              'archive_timeout = 60')
        self.assertTrue(set_result)
        set_result = self.pri_sh.executeGsguc('reload',
                                              self.constant.GSGUC_SUCCESS_MSG,
                                              'checkpoint_segments = 10')
        self.assertTrue(set_result)

        self.log.info('----查看主机query，同步是否正常----')
        self.pri_sh.check_location_consistency('primary', 3)

        self.log.info('----查询主备状态----')
        status = self.pri_sh.getDbClusterStatus('status')
        self.assertTrue(status)

        self.log.info('----归档目录不存在时创建归档目录----')
        ls_cmd = f'ls -al {self.arch_path}'
        self.log.info(ls_cmd)
        ls_result = self.pri_root.sh(ls_cmd).result()
        self.log.info(ls_result)
        if self.constant.NO_FILE_MSG in ls_result:
            mkdir_cmd = f'mkdir {self.arch_path}'
            self.log.info(mkdir_cmd)
            mkdir_result = self.pri_dbuser.sh(mkdir_cmd).result()
            self.assertEqual(mkdir_result, '')
            ls_cmd = f'ls -al {os.path.dirname(self.arch_path)}'
            self.log.info(ls_cmd)
            ls_result = self.pri_root.sh(ls_cmd).result()
            self.log.info(ls_result)

        create_result = self.pri_sh.executDbSql(self.create_sql)
        self.log.info(create_result)

        # 启动新线程插入数据
        insert_thread = ComThread(self.pri_sh.cycle_exec_sql,
                                  args=(self.insert_sql, self.loop_num,))
        insert_thread.setDaemon(True)
        insert_thread.start()

        self.log.info('----提交事务正在归档的时候删除归档目录权限----')
        chmod_cmd = f'chmod 000 {self.arch_path}'
        self.log.info(chmod_cmd)
        chmod_result = self.pri_root.sh(chmod_cmd).result()
        self.assertEqual(chmod_result, '')
        ls_cmd = f'ls -al {os.path.dirname(self.arch_path)}'
        self.log.info(ls_cmd)
        ls_result = self.pri_root.sh(ls_cmd).result()
        self.log.info(ls_result)

        self.log.info('----查看数据库状态----')
        status = self.pri_sh.getDbClusterStatus('status')
        self.assertTrue(status)

        # 插入数据数据线程执行完成
        insert_thread.join()
        insert_result = insert_thread.get_result()
        self.log.info(insert_result)

        select_result = self.pri_sh.executDbSql(self.select_sql)
        self.log.info(select_result)
        self.assertIn(str(self.max_num * self.loop_num), select_result)

        time.sleep(60)

        self.log.info('----查看日志关键信息成功----')
        find_file_cmd = 'ls -t ' + self.log_path + '|head -n2'
        self.log.info(find_file_cmd)
        find_file_result = self.pri_root.sh(find_file_cmd).result()
        self.log.info(find_file_result)

        tmppath = os.path.join(self.log_path, find_file_result.split()[0])
        cat_file_cmd = f'cat {tmppath}'
        self.log.info(cat_file_cmd)
        cat_file_result = self.pri_root.sh(cat_file_cmd).result()
        self.log.info(cat_file_result)
        self.log.info('如果最新日志为凌晨新切换日志，则添加上一日志的信息')
        if "000000.log" in cat_file_cmd.split()[0]:
            tmppath = os.path.join(self.log_path, find_file_result.split()[1])
            cat_file_cmd = f'cat {tmppath}'
            self.log.info(cat_file_cmd)
            result = self.pri_root.sh(cat_file_cmd).result()
            cat_file_result += result
            self.log.info(cat_file_result)
        self.assertIn(self.constant.FAILED_ARCHIVE_MSG, cat_file_result)

    def tearDown(self):
        self.log.info('----删除归档路径----')
        ls_cmd = f'ls -al {os.path.dirname(self.arch_path)}'
        self.log.info(ls_cmd)
        ls_result = self.pri_root.sh(ls_cmd).result()
        self.log.info(ls_result)
        rm_cmd = f'rm -rf {self.arch_path}'
        self.log.info(rm_cmd)
        rm_result = self.pri_root.sh(rm_cmd).result()
        self.log.info(rm_result)
        ls_cmd = f'ls -al {os.path.dirname(self.arch_path)}'
        self.log.info(ls_cmd)
        ls_result = self.pri_root.sh(ls_cmd).result()
        self.log.info(ls_result)

        self.log.info('----恢复配置参数----')
        self.pri_sh.executeGsguc('reload',
                                 self.constant.GSGUC_SUCCESS_MSG,
                                 'archive_mode = off')
        self.pri_sh.executeGsguc('reload',
                                 self.constant.GSGUC_SUCCESS_MSG,
                                 'archive_timeout = 0')
        self.pri_sh.executeGsguc('reload',
                                 self.constant.GSGUC_SUCCESS_MSG,
                                 'checkpoint_segments = 64')

        self.log.info('----删除表----')
        drop_result = self.pri_sh.executDbSql(self.drop_sql)
        self.log.info(drop_result)

        self.log.info('----Opengauss_Reliability_Dbsys_Case036 执行完成----')
